package com.wzq.design.business.base.user.service;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.crypto.SecureUtil;
import com.wf.captcha.SpecCaptcha;
import com.wzq.design.base.service.CommService;
import com.wzq.design.business.base.user.dto.*;
import com.wzq.design.business.base.user.entity.BaseUser;
import com.wzq.design.business.base.user.mapper.UserMapper;
import com.wzq.design.config.BaseConfig;
import com.wzq.ssm.parent.exception.BaseServiceException;
import com.wzq.ssm.parent.exception.StateCode;
import com.wzq.ssm.parent.redis.SpringRedisClient;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * @author wangzhiqiang
 * @since 2023/6/29 10:23
 */
@Service
public class LoginService extends CommService<UserMapper, BaseUser> {

    private final UserMapper userMapper;

    private final BaseConfig baseConfig;


    private final SpringRedisClient springRedisClient;

    public LoginService(UserMapper userMapper, BaseConfig baseConfig, SpringRedisClient springRedisClient) {
        this.userMapper = userMapper;
        this.baseConfig = baseConfig;
        this.springRedisClient = springRedisClient;
    }


    /**
     * 登录操作
     *
     * @param loginRequest 登录参数
     * @return 结果
     */
    public LoginResult login(LoginRequest loginRequest) {

        if (BooleanUtil.isTrue(baseConfig.getCaptcha().getEnabled())){
            String code = (String) springRedisClient.getKey(loginRequest.getCaptchaKey());
            if (code == null || !code.equals(loginRequest.getCaptchaCode())) {
                springRedisClient.delKey(loginRequest.getCaptchaKey());
                throw new BaseServiceException("验证码错误");
            }
        }

        BaseUser user = userMapper.findOneByField("loginName", loginRequest.getUsername());

        if (user == null) {
            throw new BaseServiceException("用户名和密码不正确");
        }


        String password = SecureUtil.pbkdf2(loginRequest.getPassword().toCharArray(), user.getSalt().getBytes());
        if (!password.equals(user.getPassword())) {
            throw new BaseServiceException("用户名和密码不正确");
        }
        StpUtil.login(user.getId(),baseConfig.getLoginTimeout());

        BaseUserDto baseUserDto = BaseUserDto.fromDb(user);

        StpUtil.getTokenSession().set(BaseUserDto.SESSION_USER_KEY, baseUserDto);

        return getLoginResult();
    }

    /**
     * 封装登录返回参数
     * @return 登录信息
     */
    private LoginResult getLoginResult() {
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        StpUtil.checkLogin();
        LoginResult result = new LoginResult();
        result.setTokenName(tokenInfo.getTokenName());
        result.setTokenValue(tokenInfo.getTokenValue());
        return result;
    }

    public CaptchaResult captcha() {
        CaptchaResult captchaResult = new CaptchaResult();

        if (BooleanUtil.isTrue(baseConfig.getCaptcha().getEnabled())) {
            SpecCaptcha specCaptcha = new SpecCaptcha(baseConfig.getCaptcha().getWidth(), baseConfig.getCaptcha().getHeight(), baseConfig.getCaptcha().getLen());
            String verCode = specCaptcha.text().toLowerCase();
            String key = UUID.fastUUID().toString();
            // 存入redis并设置过期时间为30分钟
            springRedisClient.setKey(key, verCode, 30, TimeUnit.MINUTES);
            captchaResult.setKey(key);
            captchaResult.setImage(specCaptcha.toBase64());
            captchaResult.setEnabled(true);
        }else {
            captchaResult.setEnabled(false);
        }

        return captchaResult;
    }


    public AuthResult getAuthData(){
        BaseUserDto userDto = StpUtil.getTokenSession().getModel(BaseUserDto.SESSION_USER_KEY, BaseUserDto.class);
        if (userDto==null){
            throw new BaseServiceException(StateCode.LOGIN_OUT,"登录过期");
        }

        AuthResult authResult=new AuthResult();
        authResult.setUser(AuthResult.fromDto(userDto));

        return authResult;
    }
}
